/*
Copyright (c) [2019] [name of copyright holder]
[Software Name] is licensed under the Mulan PSL v1.
You can use this software according to the terms and conditions of the Mulan PSL v1.
You may obtain a copy of Mulan PSL v1 at:
	http://license.coscl.org.cn/MulanPSL
THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY OR FIT FOR A PARTICULAR
PURPOSE.
See the Mulan PSL v1 for more details.
*/
#include "stdafx.h"
#include "线管.h"


using namespace std;


S_Vk线管::S_Vk线管(S_设备环境& 环境, std::string name) :S_线管(name) {
	S_绘图设备配置& 绘图设备配置 = *((S_绘图设备配置*)环境.m_绘图设备配置);
	m_设备 = 绘图设备配置.m_设备;
	//m_设备 = (VkDevice)环境.m_逻辑设备.设备;
	m_渲染通道 = 绘图设备配置.m_渲染通道;

	m_线管 = 0;
	m_线管缓存 = 0;
}

S_Vk线管::~S_Vk线管() {
	if (m_线管) vkDestroyPipeline(m_设备, m_线管, 0);
	if (m_线管) vkDestroyPipelineCache(m_设备, m_线管缓存, 0);
	
}

void S_Vk线管::f_创建线管(const S_线管创建参数& 参数, S_着色& shader) {
	S_Vk着色* vkshader = dynamic_cast<S_Vk着色*>(&shader);
	if (!vkshader) {
		std::cout<<"create shader error"<<std::endl;
		return;
	}


	VkDynamicState 动态状态[32];
	memset(动态状态, 0, sizeof(动态状态));
	动态状态[0] = VK_DYNAMIC_STATE_VIEWPORT;
	动态状态[1] = VK_DYNAMIC_STATE_SCISSOR;
	动态状态[2] = VK_DYNAMIC_STATE_LINE_WIDTH;
	动态状态[3] = VK_DYNAMIC_STATE_DEPTH_BIAS;

	VkPipelineDynamicStateCreateInfo 线管动态状态创建信息 = {};
	线管动态状态创建信息.sType = VK_STRUCTURE_TYPE_PIPELINE_DYNAMIC_STATE_CREATE_INFO;
	线管动态状态创建信息.pNext = 0;
	线管动态状态创建信息.pDynamicStates = 动态状态;
	线管动态状态创建信息.dynamicStateCount = 3;




	VkPipelineInputAssemblyStateCreateInfo 管线图元组装状态创建信息;
	管线图元组装状态创建信息.sType = VK_STRUCTURE_TYPE_PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO;
	管线图元组装状态创建信息.pNext = 0;
	管线图元组装状态创建信息.flags = 0;
	管线图元组装状态创建信息.primitiveRestartEnable = 参数.m_图元重启;
	管线图元组装状态创建信息.topology = (VkPrimitiveTopology)f_getVk绘制方式(参数.m_绘制方式);

	VkPipelineRasterizationStateCreateInfo 线管光栅状态创建;
	线管光栅状态创建.sType = VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_CREATE_INFO;
	线管光栅状态创建.pNext = 0;
	线管光栅状态创建.flags = 0;
	线管光栅状态创建.polygonMode = (VkPolygonMode)f_getVk填充方式(参数.m_填充模式);
	线管光栅状态创建.cullMode = VK_CULL_MODE_NONE;
	//线管光栅状态创建.cullMode = VK_CULL_MODE_FRONT_BIT;
	线管光栅状态创建.frontFace = VK_FRONT_FACE_COUNTER_CLOCKWISE;
	线管光栅状态创建.depthClampEnable = true;
	线管光栅状态创建.rasterizerDiscardEnable = false;
	线管光栅状态创建.depthBiasEnable = false;
	线管光栅状态创建.depthBiasConstantFactor = 参数.m_深度偏移;
	线管光栅状态创建.depthBiasClamp = 0.0;
	线管光栅状态创建.depthBiasSlopeFactor = 0.0;
	线管光栅状态创建.lineWidth = 2.0;



	VkPipelineColorBlendStateCreateInfo 线管颜色混合状态创建信息; //{
		VkPipelineColorBlendAttachmentState 线管颜色混合附件状态列表[1];
		线管颜色混合附件状态列表[0].colorWriteMask = 0xf;
		线管颜色混合附件状态列表[0].blendEnable = 参数.m_启用混合;
		
		线管颜色混合附件状态列表[0].colorBlendOp = VkBlendOp(f_getVk混合模式(参数.m_颜色混合模式));
		线管颜色混合附件状态列表[0].srcColorBlendFactor = VkBlendFactor(f_getVk混合因子(参数.m_源颜色混合因子));
		线管颜色混合附件状态列表[0].dstColorBlendFactor = VkBlendFactor(f_getVk混合因子(参数.m_目标颜色混合因子));
		//线管颜色混合附件状态列表[0].srcColorBlendFactor = VK_BLEND_FACTOR_SRC_ALPHA;
		//线管颜色混合附件状态列表[0].dstColorBlendFactor = VK_BLEND_FACTOR_ONE_MINUS_SRC_ALPHA;

		线管颜色混合附件状态列表[0].alphaBlendOp = VkBlendOp(f_getVk混合模式(参数.m_透明混合模式));
		线管颜色混合附件状态列表[0].srcAlphaBlendFactor = VkBlendFactor(f_getVk混合因子(参数.m_源透明通道因子));
		线管颜色混合附件状态列表[0].dstAlphaBlendFactor = VkBlendFactor(f_getVk混合因子(参数.m_目标透明通道因子));
		//线管颜色混合附件状态列表[0].srcAlphaBlendFactor = VK_BLEND_FACTOR_ONE;
		//线管颜色混合附件状态列表[0].dstAlphaBlendFactor = VK_BLEND_FACTOR_ZERO;
		

		线管颜色混合状态创建信息.sType = VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO;
		线管颜色混合状态创建信息.pNext = 0;
		线管颜色混合状态创建信息.flags = 0;
		线管颜色混合状态创建信息.attachmentCount = 1;
		线管颜色混合状态创建信息.pAttachments = 线管颜色混合附件状态列表;
		线管颜色混合状态创建信息.logicOpEnable = false;
		线管颜色混合状态创建信息.logicOp = VK_LOGIC_OP_AND;
		线管颜色混合状态创建信息.blendConstants[0] = 0.0f;
		线管颜色混合状态创建信息.blendConstants[1] = 0.0f;
		线管颜色混合状态创建信息.blendConstants[2] = 0.0f;
		线管颜色混合状态创建信息.blendConstants[3] = 0.0f;
	//}




	VkPipelineViewportStateCreateInfo 线管视口状态创建信息; //{
		VkViewport 视口;
		视口.minDepth = 0.0;
		视口.maxDepth = 1.0;
		视口.x = 0.0f;
		视口.y = 0.0f;
		视口.width = 参数.m_视口大小.x;
		视口.height = 参数.m_视口大小.x;

		VkRect2D 视口裁剪;
		视口裁剪.extent.width = 参数.m_裁剪大小.x;
		视口裁剪.extent.height = 参数.m_裁剪大小.y;
		视口裁剪.offset.x = 0;
		视口裁剪.offset.y = 0;

		线管视口状态创建信息.sType = VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_STATE_CREATE_INFO;
		线管视口状态创建信息.pNext = 0;
		线管视口状态创建信息.flags = 0;
		线管视口状态创建信息.viewportCount = 参数.m_视口数量;
		线管视口状态创建信息.pViewports = &视口;
		线管视口状态创建信息.scissorCount = 参数.m_视口数量;
		线管视口状态创建信息.pScissors = &视口裁剪;
	//}


	VkPipelineDepthStencilStateCreateInfo 线管深度及模板创建信息;
	线管深度及模板创建信息.sType = VK_STRUCTURE_TYPE_PIPELINE_DEPTH_STENCIL_STATE_CREATE_INFO;
	线管深度及模板创建信息.pNext = nullptr;
	线管深度及模板创建信息.flags = 0;
	线管深度及模板创建信息.depthTestEnable = 参数.m_启用深度测试;
	线管深度及模板创建信息.depthWriteEnable = 参数.m_启用写入深度;
	线管深度及模板创建信息.depthCompareOp = VK_COMPARE_OP_LESS_OR_EQUAL;
	线管深度及模板创建信息.depthBoundsTestEnable = 参数.m_启用深度边界;
	线管深度及模板创建信息.minDepthBounds = 0;
	线管深度及模板创建信息.maxDepthBounds = 1;
	线管深度及模板创建信息.stencilTestEnable = VK_TRUE;
	线管深度及模板创建信息.back.failOp = VK_STENCIL_OP_KEEP;
	线管深度及模板创建信息.back.passOp = VK_STENCIL_OP_KEEP;
	线管深度及模板创建信息.back.compareOp = VK_COMPARE_OP_ALWAYS;
	线管深度及模板创建信息.back.compareMask = 0;
	线管深度及模板创建信息.back.reference = 0;
	线管深度及模板创建信息.back.depthFailOp = VK_STENCIL_OP_KEEP;
	线管深度及模板创建信息.back.writeMask = 0;
	线管深度及模板创建信息.front = 线管深度及模板创建信息.back;

	VkPipelineMultisampleStateCreateInfo 多重采样创建信息;
	多重采样创建信息.sType = VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO;
	多重采样创建信息.pNext = 0;
	多重采样创建信息.flags = 0;
	多重采样创建信息.pSampleMask = 0;
	多重采样创建信息.rasterizationSamples = f_get多重采样Bits(参数.m_采样);
	多重采样创建信息.sampleShadingEnable = false;
	多重采样创建信息.alphaToCoverageEnable = false;
	多重采样创建信息.alphaToOneEnable = false;
	多重采样创建信息.minSampleShading = 0.0;

	VkGraphicsPipelineCreateInfo 图形线管创建信息;
	图形线管创建信息.sType = VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO;
	图形线管创建信息.pNext = nullptr;
	图形线管创建信息.flags = 0;
	图形线管创建信息.layout = vkshader->m_线管布局;
	图形线管创建信息.basePipelineHandle = VK_NULL_HANDLE;
	图形线管创建信息.basePipelineIndex = 0;
	图形线管创建信息.pDynamicState = &线管动态状态创建信息;
	图形线管创建信息.pVertexInputState = &vkshader->m_线管顶点输入状态创建信息;
	图形线管创建信息.pInputAssemblyState = &管线图元组装状态创建信息;
	图形线管创建信息.pRasterizationState = &线管光栅状态创建;
	图形线管创建信息.pColorBlendState = &线管颜色混合状态创建信息;
	图形线管创建信息.pViewportState = &线管视口状态创建信息;
	图形线管创建信息.pDepthStencilState = &线管深度及模板创建信息;
	图形线管创建信息.pMultisampleState = &多重采样创建信息;
	图形线管创建信息.pTessellationState = NULL;
	图形线管创建信息.stageCount = vkshader->m_着色阶段创建信息.size();
	图形线管创建信息.pStages = vkshader->m_着色阶段创建信息.data();
	图形线管创建信息.renderPass = m_渲染通道;
	图形线管创建信息.subpass = 0;
	
	VkPipelineCacheCreateInfo 线管缓存创建信息;
	线管缓存创建信息.sType = VK_STRUCTURE_TYPE_PIPELINE_CACHE_CREATE_INFO;
	线管缓存创建信息.flags = 0;
	线管缓存创建信息.pNext = 0;
	线管缓存创建信息.initialDataSize = 0;
	线管缓存创建信息.pInitialData = 0;
	

	VkResult res = vkCreatePipelineCache(m_设备, &线管缓存创建信息, 0, &m_线管缓存);
	if (res != VK_SUCCESS) {
		std::cout << "vkCreatePipelineCache error" << std::endl;
		//exit(-1);
	}


	res = vkCreateGraphicsPipelines(m_设备, m_线管缓存, 1, &图形线管创建信息, 0, &m_线管);
	if (res != VK_SUCCESS) {
		std::cout << "vkCreateGraphicsPipelines error" << std::endl;
		//exit(-1);
	}
}












S_Vk计算线管::S_Vk计算线管(S_设备环境& 环境, std::string name) :S_线管(name) {
	m_设备				= (VkDevice)环境.m_逻辑设备.设备;
	S_绘图设备配置* ini	= (S_绘图设备配置*)环境.m_逻辑设备.pNext;

}

S_Vk计算线管::~S_Vk计算线管()
{
}

void S_Vk计算线管::f_创建线管(const S_线管创建参数& 参数, S_着色& shader) {
	S_Vk着色* vkshader = dynamic_cast<S_Vk着色*>(&shader);
	if (!vkshader) return;


	VkComputePipelineCreateInfo pipelineInfo;
	pipelineInfo.sType = VK_STRUCTURE_TYPE_COMPUTE_PIPELINE_CREATE_INFO;
	pipelineInfo.pNext = NULL;
	pipelineInfo.flags = 0;
	pipelineInfo.basePipelineHandle = VK_NULL_HANDLE;
	pipelineInfo.basePipelineIndex = 0;
	pipelineInfo.layout = vkshader->m_线管布局;
	pipelineInfo.stage = vkshader->m_着色阶段创建信息[0];


	VkPipelineCacheCreateInfo pipelineCacheInfo;
	pipelineCacheInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_CACHE_CREATE_INFO;
	pipelineCacheInfo.pNext = NULL;
	pipelineCacheInfo.initialDataSize = 0;
	pipelineCacheInfo.pInitialData = NULL;
	pipelineCacheInfo.flags = 0;
	VkResult result = vkCreatePipelineCache(m_设备, &pipelineCacheInfo, NULL, &m_线管缓存);
	assert(result == VK_SUCCESS);

	result = vkCreateComputePipelines(m_设备, m_线管缓存, 1, &pipelineInfo, nullptr, &m_线管);
	assert(result == VK_SUCCESS);
}










S_Vk光追线管::S_Vk光追线管(S_设备环境& ctx, std::string name) :S_线管(name) {
	m_Ctx = &ctx;
	m_线管 = nullptr;
	m_着色 = nullptr;
	m_参数布局.resize(1);

}


void S_Vk光追线管::f_创建线管(const S_线管创建配置& 参数, S_着色& shader) {
	auto 绘图配置 = f_vk_get绘图环境(*m_Ctx);
	m_着色 = static_cast<S_Vk着色*>(&shader);

	//S_Vk着色器创建参数 参数转换(参数);
	m_线管布局 = f_vk_创建线管布局(绘图配置->m_设备, m_着色->m_参数布局);

	/*VkRayTracingPipelineCreateInfoKHR rayTracingPipelineCI{VK_STRUCTURE_TYPE_RAY_TRACING_PIPELINE_CREATE_INFO_KHR};
	rayTracingPipelineCI.stageCount = m_着色->m_着色阶段创建信息.size();
	rayTracingPipelineCI.pStages = m_着色->m_着色阶段创建信息.data();
	rayTracingPipelineCI.groupCount = m_着色->m_光追着色组创建信息.size();
	rayTracingPipelineCI.pGroups = m_着色->m_光追着色组创建信息.data();
	rayTracingPipelineCI.maxPipelineRayRecursionDepth = 2;
	rayTracingPipelineCI.layout = m_线管布局;
	绘图配置->vkCreateRayTracingPipelines(绘图配置->m_设备, VK_NULL_HANDLE, VK_NULL_HANDLE, 1, &rayTracingPipelineCI, nullptr, &m_线管);*/

	m_线管 = f_pipeline_创建(m_着色, m_线管布局, *m_Ctx);
	
}

void S_Vk光追线管::f_重置线管() {
	

	return;
	//uint32 要销毁的着色器数量 = E_光追绑定阶段ID::e_光追阶段_材质回调;
	//for (uint32 i = E_光追绑定阶段ID::e_光追阶段_材质回调; i < 要销毁的着色器数量; ++i) {
	//}
	//m_着色->f_销毁着色器(4);
}

void S_Vk光追线管::f_销毁线管() {
	
}

/*void S_Vk光追线管::f_添加着色器(const std::string path, int32 loc) {
	if (m_着色->m_光追着色器.size() <= loc) {

	}
	f_vkShader_创建着色器(m_着色, path, loc, true);
}*/

void S_Vk光追线管::f_销毁着色器(uint32 id) {
	if (id < m_着色->m_光追着色器.size()) {
		vkDestroyShaderModule(m_着色->m_设备, m_着色->m_着色阶段创建信息[id].module, 0);

		m_着色->m_光追着色器.erase(m_着色->m_光追着色器.begin() + id);
		m_着色->m_着色阶段创建信息.erase(m_着色->m_着色阶段创建信息.begin() + id);
		m_着色->m_光追着色组创建信息.erase(m_着色->m_光追着色组创建信息.begin() + id);
	}

}

VkPipeline f_pipeline_创建(S_Vk着色* 着色, VkPipelineLayout 线管布局, S_设备环境& ctx) {
	auto 绘图配置 = f_vk_get绘图环境(ctx);

	VkRayTracingPipelineCreateInfoKHR rayTracingPipelineCI{ VK_STRUCTURE_TYPE_RAY_TRACING_PIPELINE_CREATE_INFO_KHR };
	rayTracingPipelineCI.stageCount = 着色->m_着色阶段创建信息.size();
	rayTracingPipelineCI.pStages = 着色->m_着色阶段创建信息.data();
	rayTracingPipelineCI.groupCount = 着色->m_光追着色组创建信息.size();
	rayTracingPipelineCI.pGroups = 着色->m_光追着色组创建信息.data();
	rayTracingPipelineCI.maxPipelineRayRecursionDepth = 8;
	rayTracingPipelineCI.layout = 线管布局;

	VkPipeline 线管;
	auto err = 绘图配置->vkCreateRayTracingPipelines(绘图配置->m_设备, VK_NULL_HANDLE, VK_NULL_HANDLE, 1, &rayTracingPipelineCI, nullptr, &线管);

	return 线管;
}
